/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 *
 */
import { expect } from '@jest/globals';
import fs from 'fs';
import fse from 'fs-extra';
import path from 'path';

import { runHvigorAsync, runHvigorFailAsync } from '../../common/common';
import { commonFileOperation } from '../../plugins/common-fun';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType,
} from '../../plugins/project-builder/models/constants';
import { TestCaseBuilder } from '../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../plugins/task-builder/test-case';
import { TestTaskOptionBuilder } from '../../plugins/task-builder/test-task-option';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: APIVersion.API10,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility,
  },
};

const testfun: TestCaseFun = async (project, taskConfig, record) => {
  const projectRootPath = project.projectRootPath();

  const entryModule = project.getModule('entry');
  const entryRootPath = entryModule.moduleRootPath();
  const sourceRootPath = path.resolve(entryRootPath, 'src', 'main', 'ets');
  const commands: string[] =
    ' --mode module -p product=default -p module=entry@default assembleHap --analyze=normal --parallel --incremental --no-daemon'.split(' ');
  await commonFileOperation(path.resolve(sourceRootPath, 'pages', 'Index.ets'), async (json) => {
    return `
    @Entry
    @Component
    struct Index {
      @State message: string = 'Hello World';
    
      build() {
        Row() {
          Column() {
            Text(this.message)
              .fontSize(50)
              .fontWeight(FontWeight.Bold)
          }
          .width('100%')
        }
        .height('100%')
      }
    }
    `;
  });
  const result = await runHvigorAsync(projectRootPath, commands);
  record.addStep('首次编译', result);
  expect(result.stdout).toContain('BUILD SUCCESSFUL');
  const cacheDir = path.resolve(
    entryRootPath,
    'build',
    'default',
    'cache',
    'default',
    'default@CompileArkTS',
    'esmodule',
    'debug',
    'compiler.cache',
    'modules',
  );
  const cacheFiles = getFiles(cacheDir);
  getFiles(sourceRootPath).forEach((file) => {
    const sourceFileName = path.basename(file);
    const isExist = cacheFiles.some((fileName) => fileName.startsWith(`${sourceFileName}-`));
    expect(isExist).toBe(true);
  });

  const testEts = path.resolve(sourceRootPath, 'pages', 'test.ets');
  fse.ensureFileSync(testEts);
  await commonFileOperation(testEts, async (json) => {
    return 'export const a: string = \'a\';';
  });
  await commonFileOperation(path.resolve(sourceRootPath, 'pages', 'Index.ets'), async (json) => {
    return `
    import { a } from './test';

    @Entry
    @Component
    struct Index {
      @State message: string = 'Hello World' + a;
    
      build() {
        Row() {
          Column() {
            Text(this.message)
              .fontSize(50)
              .fontWeight(FontWeight.Bold)
          }
          .width('100%')
        }
        .height('100%')
      }
    }
    `;
  });
  const result1 = await runHvigorAsync(projectRootPath, commands);
  record.addStep('2. 新增test.ets被Index.ets引用，增量编译', result);
  expect(result1.stdout).toContain('BUILD SUCCESSFUL');
  const cacheFiles1 = getFiles(cacheDir);
  getFiles(sourceRootPath).forEach((file) => {
    const sourceFileName = path.basename(file);
    const isExist = cacheFiles1.some((fileName) => fileName.startsWith(`${sourceFileName}-`));
    expect(isExist).toBe(true);
  });
};

function getFiles(dir: string) {
  const files = fs.readdirSync(dir);
  const filePaths = [];

  for (const file of files) {
    const filePath = path.join(dir, file);
    const stats = fs.statSync(filePath);
    if (stats.isDirectory()) {
      // 如果是目录，则递归查找
      getFiles(filePath);
    } else {
      // 如果是文件，则添加到结果中
      filePaths.push(filePath);
    }
  }
  return filePaths;
}

TestCaseBuilder.builder()
  .caseName('COMPILER_CACHE')
  .description('看护compiler.cache文件夹下面生成的缓存文件')
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.L0).build())
  .testFun(testfun)
  .load();
